package org.moonlight.jvm.classfile;

import org.moonlight.jvm.classfile.attribute.AttributeInfo;
import org.moonlight.jvm.classfile.attribute.CodeAttribute;
import org.moonlight.jvm.classfile.attribute.ConstantValueAttribute;
import org.moonlight.jvm.classfile.constant.StaticConstantPool;

/**
 * 类的成员信息 - 主要是用于存储 字段和方法的信息
 *
 * 字段和方法的基本结构大致相同，差别仅在于属性表。
 * 下面是Java虚拟机规范给出的字段结构定义:
 *  field_info {
 *      u2              access_flags
 *      u2              name_index
 *      u2              descriptor_index
 *      u2              attributes_count
 *      attribute_info  attributes[attributes_count]
 *  }
 *
 * @author Moonlight
 * @createTime 2023/8/15 9:27
 **/
public class MemberInfo {

    /** 所属ClassFile的静态常量池 **/
    private final StaticConstantPool scp;
    /** 访问标志位 **/
    private final int accessFlags;
    /** 字段/方法 名称(符号引用)在静态常量池中的索引下标 **/
    private final int nameIdx;
    /** 字段/方法 描述符(符号引用)在静态常量池中的索引下标 **/
    private final int descriptorIdx;
    /** 字段/方法 属性信息表 **/
    private final AttributeInfo[] attributes;

    public MemberInfo(ClassReader classReader, StaticConstantPool scp) {
        this.scp = scp;
        this.accessFlags = classReader.readUint16();
        this.nameIdx = classReader.readUint16();
        this.descriptorIdx = classReader.readUint16();
        this.attributes = AttributeInfo.readAttributes(classReader, scp);
    }

    public int getAccessFlags() {
        return this.accessFlags;
    }

    public String getName() {
        return this.scp.getUtf8(this.nameIdx);
    }

    public String getDescriptor() {
        return this.scp.getUtf8(this.descriptorIdx);
    }

    /**
     * 获取 代码属性
     *
     * @return CodeAttribute
     * @createTime 11:03 2023/8/23
     * @author moonlight
     **/
    public CodeAttribute codeAttribute() {
        for (AttributeInfo info : this.attributes) {
            if (info instanceof CodeAttribute) {
                return (CodeAttribute) info;
            }
        }
        return null;
    }
    /**
     * 获取 常量属性
     *
     * @return CodeAttribute
     * @createTime 11:03 2023/8/23
     * @author moonlight
     **/
    public ConstantValueAttribute constantValueAttribute() {
        for (AttributeInfo info : this.attributes) {
            if (info instanceof ConstantValueAttribute) {
                return (ConstantValueAttribute) info;
            }
        }
        return null;
    }

    /**
     * 通过 类文件数据读取解析器{@link ClassReader} 从 类文件数据{@link ClassFile} 读取解析出 成员信息{@link MemberInfo}数组
     *
     * @param reader 类文件数据读取解析器
     * @param scp 类文件静态常量池 {@link StaticConstantPool}
     * @return MemberInfo[] 成员信息数组
     * @createTime 10:10 2023/8/15
     * @author moonlight
     **/
    public static MemberInfo[] readMembers(ClassReader reader, StaticConstantPool scp) {
        int fieldCnt = reader.readUint16();
        MemberInfo[] memberInfos = new MemberInfo[fieldCnt];
        for (int i = 0; i < fieldCnt; i++) {
            memberInfos[i] = new MemberInfo(reader, scp);
        }
        return memberInfos;
    }

}
